package com.faner4cloud.yun.common.util.batch;


import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * @author ...zz
 * @version v1
 * @summary 可分批的数据
 * @since 2022/5/12 5:28 PM
 */
public interface Batchable<T> {
	/**
	 * 适用于批处理函数的返回值是int的场景，该方法会将批处理函数的返回值的累加。
	 * </p>
	 * 注意：如果批处理函数返回NULL，则视为0；
	 *
	 * @author huisman (liuhui01@lianjia.com)
	 * @version v1
	 * @param batchHandler 批处理函数
	 * @return int
	 */
	int sumEach(Function<BatchContext<T>, Integer> batchHandler);

	/**
	 * 该方法会将批处理函数的返回值收集到List里并返回。
	 * 注意：如果批处理函数返回NULL，则忽略返回值；
	 *
	 *
	 * @author huisman (liuhui01@lianjia.com)
	 * @version v1
	 * @param R 批处理函数返回类型
	 * @param batchHandler 批处理函数
	 * @return List
	 */
	<R> List<R> listEach(Function<BatchContext<T>, R> batchHandler);

	/**
	 * 适用于通用场景，批处理函数的返回类型为泛型<code>&lt;R&gt;<code>，该方法最终会返回一个Stream<code>&lt;R&gt;供后续聚合处理。
	 * </br>
	 * 注意：如果批处理函数返回NULL，则忽略返回值；由于Stream会延迟计算，因此客户端需要进一步调用Stream的terminal
	 * operation才会触发批处理，比如：count(),collect(),foreach(),reduce()。
	 *
	 * @author huisman (liuhui01@lianjia.com)
	 * @version v1
	 * @param R 批处理函数返回类型
	 * @param batchHandler 批处理函数
	 * @return 返回一个Stream
	 * @summary 分批处理数据并返回类型为<code>&lt;R&gt;的Stream
	 * @since 2018年7月11日
	 */
	<R> Stream<R> each(Function<BatchContext<T>, R> batchHandler);

	void foreach(Consumer<BatchContext<T>> batchConsumer);

	/**
	 * 分批数据的上下文信息，包括分批大小、第几批等基本信息
	 */
	static class BatchContext<T> {
		private final int batchSize;
		private final int totalSize;
		private final int batchIndex;
		private final boolean lastBatch;
		private final List<T> data;

		BatchContext(List<T> data, int totalSize, int batchSize, int batchIndex, boolean lastBatch) {
			this.batchIndex = batchIndex;
			this.totalSize = totalSize;
			this.batchSize = batchSize;
			this.lastBatch = lastBatch;
			this.data = data;
		}

		/**
		 * 数据总共多少条
		 */
		public int getTotalSize() {
			return this.totalSize;
		}

		/**
		 * 是否是最后一批数据
		 */
		public boolean isLastBatch() {
			return this.lastBatch;
		}

		/**
		 * 每批处理多少条数据
		 */
		public int getBatchSize() {
			return this.batchSize;
		}

		/**
		 * 当前是第几批，从1开始
		 */
		public int getBatchIndex() {
			return this.batchIndex;
		}

		/**
		 * 本批需要处理的数据集，不为null，另外，data支持序列化。
		 */
		public List<T> getData() {
			return this.data;
		}

		@Override
		public String toString() {
			return "BatchContext [batchSize=" + batchSize + ", totalSize=" + totalSize + ", batchIndex="
				+ batchIndex + ", lastBatch=" + lastBatch + ", data=" + data + "]";
		}

	}
}

